import React from 'react';
import { Button, Input, Progress, Tag, Form } from 'antd';
import useUploadOss from '@/hooks/useUploadOss';
import Previewer from '../Previewer';
import { getFormatValue, getFileType, getErrors } from '../utils';
import { PREVIEW_TYPE } from '../constant';

/**
 * 脱离antd的Upload实现
 *
 * 只支持单文件
 *
 * buildInRules 目前支持两种内建校验 { max: 3, type: ['jpg', 'png'] };
 */

const btnStyle = {
    opacity: 0,
    width: '100%',
    height: '100%',
    position: 'absolute',
    left: 0,
    top: 0,
    cursor: 'pointer'
};

// 展示已上传的资源
const UploadedContent = React.memo(({ value, error, editable, handleRemove }) => {
    const previewRef = React.useRef();

    const formatValue = getFormatValue(value); // 简单处理
    const fileType = getFileType(formatValue);

    const handlePreview = () => {
        previewRef.current.show(formatValue, value);
    };

    return (
        <>
            {value && (
                <>
                    <Tag closable={editable} onClose={handleRemove}>
                        {formatValue}
                    </Tag>
                    {PREVIEW_TYPE.includes(fileType) && !error && (
                        <Button type="link" onClick={handlePreview}>
                            预览
                        </Button>
                    )}
                    {!error && (
                        <Button type="link" onClick={() => window.open(value)}>
                            下载
                        </Button>
                    )}
                </>
            )}
            <Input value={value} type="hidden" />
            <Previewer ref={previewRef} />
        </>
    );
});

const UploadBase = React.forwardRef(
    ({ onChange, value, initialValue, buildInRules, error, setError, ...rest }, ref) => {
        const [uploadFile, uploadProgress] = useUploadOss();

        // 有错误时强制校验
        React.useEffect(() => {
            if (error) onChange(value);
        }, [error]);

        React.useEffect(() => {
            if (initialValue) onChange(initialValue);
        }, [initialValue]);

        const handleChange = async e => {
            const targetFile = e.target.files[0];
            setError(null); // 避免同样的错误不校验
            const checkError = getErrors(buildInRules, targetFile);
            if (checkError) {
                onChange(targetFile.name);
                setError(checkError);
                return;
            }
            const result = await uploadFile(targetFile);
            onChange(result);
        };

        const handleRemove = () => {
            onChange('');
            setError(null);
        };

        const renderContent = () => {
            if (value) {
                return <UploadedContent handleRemove={handleRemove} error={error} value={value} {...rest} />;
            }

            if (uploadProgress && uploadProgress < 100) {
                return <Progress percent={parseInt(uploadProgress, 10)} />;
            }

            return (
                <Button icon="upload" style={{ position: 'relative' }}>
                    上传文件
                    <input type="file" onChange={handleChange} style={btnStyle} />
                </Button>
            );
        };

        return <div ref={ref}>{renderContent()}</div>;
    }
);

const UploadOssLite = React.forwardRef(
    ({ form, fieldName, buildInRules = {}, initialValue, editable = true, required = false, ...rest }, ref) => {
        if (!editable) {
            return (
                <Form.Item {...rest}>
                    <UploadedContent editable={editable} value={initialValue} />
                </Form.Item>
            );
        }

        const { getFieldDecorator } = form;
        const [error, setError] = React.useState(); // 为了前置校验

        const uploadBaseProp = {
            error,
            setError,
            buildInRules,
            editable,
            initialValue
        };

        return (
            <Form.Item {...rest}>
                {getFieldDecorator(fieldName, {
                    rules: [
                        {
                            validator(rule, value, callback) {
                                if (required && !value) {
                                    callback(`${rest?.label}不能为空`);
                                    return;
                                }
                                if (value && error) {
                                    callback(error);
                                } else {
                                    callback();
                                }
                            }
                        }
                    ]
                })(<UploadBase ref={ref} {...uploadBaseProp} />)}
            </Form.Item>
        );
    }
);

export default UploadOssLite;
